/*
 * Created on 2005-3-9
 */
package com.hd123.rumba.runtime;

import javax.naming.NamingException;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.cfg.Configuration;

import org.apache.log4j.Logger;

/**
 * @author caili
 */
public class HibernateSession2 {

  private static final int MAXFACTORIES = 2;
  private static SessionFactory[] sessionFactories = new SessionFactory[MAXFACTORIES];
  protected static final ThreadLocal[] sessions = new ThreadLocal[MAXFACTORIES];

  static {
    try {
      for (int i = 0; i < sessions.length; ++i)
        sessions[i] = new ThreadLocal();
      setEnabled("true");
    } catch (Throwable th) {
      throw new ExceptionInInitializerError(th);
    }
  }

  public static void setEnabled(String enabled) throws HibernateException {
    setEnabled(0, enabled, "/hibernate.cfg.xml");
  }

  public static void setEnabled(int idx, String enabled, String resource) throws HibernateException {
    checkIdx(idx);
    if ("true".equals(enabled)) {
      if (sessionFactories[idx] == null) {
        sessionFactories[idx] = new Configuration().configure(resource).buildSessionFactory();
        Logger.getLogger(HibernateSession.class).info(
            "Hibernate session " + idx + " initialized by " + resource);
      }
    }
  }

  public static Session getSession() throws HibernateException {
    return getSession(0);
  }

  public static Session getSession(int idx) throws HibernateException {
    checkIdx(idx);
    Session s = (Session) sessions[idx].get();
    if (s == null) {
      s = sessionFactories[idx].openSession();
      Logger.getLogger(HibernateSession.class).debug(
          "Hibernate session." + idx + ".get." + Thread.currentThread().getId());
      sessions[idx].set(s);
    }
    return s;
  }

  public static void closeSession() throws HibernateException {
    closeSession(0);
  }

  public static void closeSession(int idx) throws HibernateException {
    checkIdx(idx);
    Session s = (Session) sessions[idx].get();
    sessions[idx].set(null);
    if (s != null) {
      s.close();
      Logger.getLogger(HibernateSession.class).debug(
          "Hibernate session." + idx + ".close." + Thread.currentThread().getId());
    }
  }

  public static Transaction beginTransaction() throws HibernateException {
    return beginTransaction(0);
  }

  public static Transaction beginTransaction(int idx) throws HibernateException {
    checkIdx(idx);
    return getSession(idx).beginTransaction();
  }

  public static void commit(Transaction tx) throws HibernateException {
    commit(0, tx);
  }

  public static void commit(int idx, Transaction tx) throws HibernateException {
    checkIdx(idx);
    tx.commit();
    getSession(idx).clear();
  }

  public static void commit(Transaction tx, boolean clear) throws HibernateException, NamingException {
    commit(0, tx, clear);
  }

  public static void commit(int idx, Transaction tx, boolean clear) throws HibernateException,
      NamingException {
    checkIdx(idx);
    tx.commit();
    if (clear) {
      getSession(idx).clear();
    }
  }

  public static void rollback(Transaction tx) throws HibernateException {
    rollback(0, tx);
  }

  public static void rollback(int idx, Transaction tx) throws HibernateException {
    checkIdx(idx);
    tx.rollback();
    getSession(idx).clear();
  }

  public static void rollback(Transaction tx, boolean clear) throws HibernateException {
    rollback(0, tx, clear);
  }

  public static void rollback(int idx, Transaction tx, boolean clear) throws HibernateException {
    checkIdx(idx);
    tx.rollback();
    if (clear) {
      getSession(idx).clear();
    }
  }

  private static void checkIdx(int idx) throws HibernateException {
    if (idx > MAXFACTORIES)
      throw new HibernateException("idx应小于" + MAXFACTORIES);
  }
}
